package com.nervenets.template.controller.role;

import com.nervenets.general.aspect.SysLog;
import com.nervenets.general.entity.ResponseResult;
import com.nervenets.general.jwt.aspect.JwtRole;
import com.nervenets.general.jwt.aspect.JwtSecurity;
import com.nervenets.general.jwt.util.JwtUtils;
import com.nervenets.general.model.MenuRole;
import com.nervenets.general.web.BaseEntityController;
import com.nervenets.general.web.params.BoolIdParams;
import com.nervenets.general.web.params.QueryParams;
import com.nervenets.template.controller.role.dto.RoleModel;
import com.nervenets.template.controller.role.params.RoleChildrenParams;
import com.nervenets.template.controller.role.params.RoleGroupFormParams;
import com.nervenets.template.controller.role.params.RoleGroupPagingParams;
import com.nervenets.template.controller.role.params.UserRoleParams;
import com.nervenets.template.hibernate.domain.user.Manager;
import com.nervenets.template.hibernate.domain.user.RoleGroup;
import com.nervenets.template.service.ManagerService;
import com.nervenets.template.service.RoleGroupService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.domain.Sort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Api(value = "权限接口v1", tags = "权限类接口")
@RestController
@RequestMapping("/api/role")
@JwtRole(group = "system", groupName = "系统管理", function = "role", functionName = "权限管理")
public class RoleGroupController extends BaseEntityController<RoleGroup, RoleGroupService, RoleGroupFormParams, RoleGroupPagingParams, RoleGroup, RoleGroup> {
    @Resource
    private ManagerService managerService;

    @ApiOperation(value = "所有角色")
    @PostMapping({"/all"})
    public ResponseEntity<ResponseResult<List<RoleGroup>>> all() {
        return successMessage(service.findAll(new QueryParams<RoleGroup>() {
            @Override
            public void generateSpecification(List<Predicate> predicates, Root<RoleGroup> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                addAscOrderBy(root.get("queue"));
            }
        }));
    }

    @SysLog
    @ApiOperation("添加用户到权限组")
    @PostMapping("/user")
    public ResponseEntity<ResponseResult<Void>> user(@Valid @RequestBody UserRoleParams params) {
        RoleGroup roleGroup = service.findOne(params.getRoleGroupId(), "您要操作的权限组不存在");

        for (Long userId : params.getUserIds()) {
            final Manager manager = managerService.findOne(userId);
            if (null != manager) {
                if (params.isAdd()) {
                    if (!manager.getRoleGroups().contains(roleGroup)) {
                        manager.getRoleGroups().add(roleGroup);
                    }
                } else {
                    manager.getRoleGroups().remove(roleGroup);
                }
                managerService.save(manager);
            }
        }

        return successMessage();
    }

    @ApiOperation("所有权限组列表")
    @PostMapping("/groups")
    public ResponseEntity<ResponseResult<List<RoleModel>>> groups() {
        List<RoleGroup> groups = service.findAll(new QueryParams<RoleGroup>() {
            @Override
            public void generateSpecification(List<Predicate> predicates, Root<RoleGroup> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                predicates.add(builder.equal(root.get("customerId"), JwtUtils.getUser().getId()));
            }
        }, Sort.by(Sort.Direction.DESC, "id"));
        List<RoleModel> models = new ArrayList<>();
        HashMap<Long, List<RoleModel>> map = new HashMap<>();
        for (RoleGroup group : groups) {
            if (0 == group.getParentId()) {
                models.add(new RoleModel(group, managerService));
            } else {
                if (map.containsKey(group.getParentId())) {
                    map.get(group.getParentId()).add(new RoleModel(group, managerService));
                } else {
                    ArrayList<RoleModel> children = new ArrayList<>();
                    children.add(new RoleModel(group, managerService));
                    map.put(group.getParentId(), children);
                }
            }
        }

        models.forEach(roleModel -> {
            if (map.containsKey(roleModel.getId())) {
                roleModel.setChildren(map.get(roleModel.getId()));
            }
        });

        return successMessage(models);
    }

    @ApiOperation("子权限组列表")
    @PostMapping("/children")
    public ResponseEntity<ResponseResult<List<RoleGroup>>> children(@Valid @RequestBody RoleChildrenParams params) {
        return successMessage(service.findAll(new QueryParams<RoleGroup>() {
            @Override
            public void generateSpecification(List<Predicate> predicates, Root<RoleGroup> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                predicates.add(builder.equal(root.get("parentId"), params.getRoleParentId()));
            }
        }, Sort.by("id")));
    }

    @ApiOperation("权限列表明细")
    @PostMapping("/allRoles")
    public ResponseEntity<ResponseResult<List<MenuRole>>> allRoles() {
        return successMessage(JwtUtils.getAllMenuRoles());
    }

    @SysLog
    @ApiOperation(value = "权限组禁用启用")
    @PostMapping("/enable")
    @JwtSecurity(permission = "enable", permissionName = "禁用启用")
    public ResponseEntity<ResponseResult<RoleGroup>> enable(@Valid @RequestBody BoolIdParams params) {
        RoleGroup roleGroup = service.findById(params.getTargetId()).orElse(null);
        if (null == roleGroup) return errorMessage(HttpStatus.NOT_FOUND.value(), "您要操作的权限组不存在");
        roleGroup.setEnable(params.isYes());
        service.save(roleGroup);
        return successMessage(roleGroup);
    }

}
